<?php

/**
 * Zeed Platform Project
 * Based on Zeed Framework & Zend Framework.
 *
 * LICENSE
 * http://www.zeed.com.cn/license/
 *
 * @category Zeed
 * @package Zeed_ChangeMe
 * @subpackage ChangeMe
 * @copyright Copyright (c) 2010 Zeed Technologies PRC Inc. (http://www.zeed.com.cn)
 * @author Zeed Team (http://blog.zeed.com.cn)
 * @since 2010-12-6
 * @version SVN: $Id$
 */
class ImageController extends WorkbenchAdminAbstract
{

    const sourceRootPath = "../upload/";
    private $sourcePath = "";

    const outRootPath = "../upload/";
    private $outPath = "";
    const water = "../view/static/workbench/admin/images/water.png";

    const fontPath = '../view/static/panel/fonts/msyh.ttf';

    private static $httpResponseDomain = "http://192.168.0.106:12345";

    /**
     * 图片处理
     */
    public function index()
    {
        $this->addResult(self::RS_SUCCESS, 'json');

        /* 接收参数 */
        $_id = trim($this->input->query('_id'));
        $card_id = $this->input->query('card_id', 0);

        /* ajax 加载数据 */
        if ($this->input->isPOST()) {
            /* 获取文件信息 */
            $attachment_info = Attachment_Model_Content::instance()->fetchByPK($_id);
            if (empty($attachment_info)) {
                $attachment_info = Attachment_Model_Content_Temp::instance()->fetchByPK($_id);
            }
            if (!empty($attachment_info)) {
                $filepath = Support_Image_Url::getImageUrl($attachment_info[0]['filepath']);
            }

            /* 获取相关文件列表 */
            $attachment_list = array();
            if ($card_id) {
                $card_info = Archive_Model_Card::instance()->fetchByPK($card_id);
                if (!empty($card_info) && $card_info[0]['attachments_img']) {
                    $attachments_img = explode(',', $card_info[0]['attachments_img']);
                    $attachment_list = Attachment_Model_Content::instance()->fetchByPK($attachments_img,
                        array('_id', 'filepath', 'title'));
                    foreach ($attachment_list as $k => &$v_al) {
                        $v_al['filepath'] = Support_Image_Url::getImageUrl($v_al['filepath']);
                    }
                }
            }

            /* 处理添加时的编辑情况 */
            if (empty($attachment_list) && !empty($attachment_info)) {
                $attachment_list[] = array(
                    '_id' => $attachment_info[0]['_id'],
                    'filepath' => $filepath,
                    'title' => $attachment_info[0]['title']
                );
            }

            /* 获取图片处理历史 */
            $where_clipimage = array('pid' => $_id, 'mediatype' => 'image', 'status' => 1, 'userid' => $this->_userid);
            $clip_images = Attachment_Model_Content::instance()->fetchByWhere($where_clipimage);
            if (!empty($clip_images)) {
                foreach ($clip_images as $k => &$v_i) {
                    /* 处理截图地址 */
                    $v_i['filepath'] = Support_Image_Url::getImageUrl($v_i['filepath']);

                    /* 处理扩展信息 */
                    if (!empty($v_i['extra'])) {
                        $extra_i = json_decode($v_i['extra'], true);
                        $v_i['gmt'] = isset($extra_i['gmt']) ? $extra_i['gmt'] : '';
                    }
                }
            }

            $data = array(
                '_id' => $_id,
                'card_id' => $card_id,
                'filepath' => isset($filepath) ? $filepath : '',
                'width' => $attachment_info[0]['image_width'],
                'height' => $attachment_info[0]['image_height'],
                'clip_images' => !empty($clip_images) ? $clip_images : array(),
                'attachment_list' => $attachment_list
            );

            $this->setData('data', $data);
            return self::RS_SUCCESS;
        }

        $this->setData('data', $data);
        $this->addResult(self::RS_SUCCESS, 'php', 'image.index');
        return parent::multipleResult(self::RS_SUCCESS);
    }

    /**
     * 图片处理
     */
    public function operate()
    {
        $this->addResult(self::RS_SUCCESS, 'json');

        /* 接收参数 */
        $uuid = trim($this->input->query('_id'));

        try {
            /* 检查请求方式 */
            if (!$this->input->isPOST()) {
                throw new Zeed_Exception('请求方式错误');
            }

            $config = Zeed_Config::loadGroup('urlmapping');
            self::$httpResponseDomain = $config['upload_cdn'];

            $imginfo = Attachment_Model_Content::instance()->fetchByPK($uuid);
            if (empty($imginfo)) {
                $imginfo = Attachment_Model_Content_Temp::instance()->fetchByPK($uuid);
            }
            if (empty($imginfo)) {
                throw new Zeed_Exception('image info not exists', 101);
            }

            //处理源文件
            $this->sourcePath = realpath(self::sourceRootPath) . $imginfo[0]['filepath'];    //storage path

            //处理输出文件
            self::initPath(self::outRootPath);

            $uuid = self::outFile($imginfo[0]['_id']);
            $outFileName = $uuid . self::fileextension($imginfo[0]['filepath']);
            $this->outPath = realpath(self::outRootPath) . DIRECTORY_SEPARATOR . $outFileName;  //storage path
            copy($this->sourcePath, $this->outPath);
            // 缩放
            $this->scaling();

            // 处理滤镜
            $this->filterImage();

            // 添加水印
            $this->watermark();

            // 旋转
            $this->rotateImage();

            // 裁剪
            $this->tailoring();
            // 录入图片主表
            $hashcode = md5_file($this->outPath);
            list($width, $height, $type, $attr) = getimagesize($this->outPath);
            $filesize = filesize($this->outPath);
            $timenow = Util_Timer::getMicrotime();

            // $filepath = DIRECTORY_SEPARATOR . self::realSavePathSameFolder($hashcode) . self::fileextension($imginfo[0]['filepath']);

            $filepath = self::realSavePathSameFolder($imginfo[0]['filepath']);
            $exec_mv = ' mv ' . $this->outPath . '  ' . realpath(self::outRootPath) . $filepath . " && echo success ";
            self::initPath(dirname(realpath(self::outRootPath) . $filepath));
            if ($res = exec($exec_mv) != 'success') {
                throw new Zeed_Exception('mv file err');
            }

            $insert = array(
                'pid' => $imginfo[0]['_id'],
                'userid' => $this->_userid,
                'title' => $this->renameTitle($imginfo[0]['title'], 'image_operate'),
                'mediatype' => $imginfo[0]['mediatype'],
                'mimetype' => $imginfo[0]['mimetype'],
                'suffix' => $imginfo[0]['suffix'],
                'image_width' => $width,
                'image_height' => $height,
                'filepath' => $filepath,
                'filesize' => $filesize,
                'hashcode' => $hashcode,
                'folder_hid' => '',
                'order_id' => $imginfo[0]['order_id'],
                'source_code' => 2,
                'extra' => $imginfo[0]['extra'],
                'status' => $imginfo[0]['status'],
                'ctime' => $timenow,
                'mtime' => $timenow,
            );
            $clip_id = Attachment_Model_Content::instance()->addForEntity($insert);

            $responsePath = self::$httpResponseDomain . $config['upload_url'] . $filepath;
            $data['imgpath'] = $responsePath;
            $data = array(
                '_id' => $clip_id,
                'imgpath' => $responsePath
            );
            $this->setData('data', $data);
        } catch (Zeed_Exception $e) {
            $this->setStatus($e->getCode() ? $e->getCode() : 1);
            $this->setError('处理失败 : ' . $e->getMessage());
        } catch (ImagickException $e) {
            $this->setStatus($e->getCode() ? $e->getCode() : 1);
            $this->setError('截取 : ' . $e->getMessage());
        }

        return self::RS_SUCCESS;
    }


    // 滤镜处理
    private function filterImage()
    {
        $request = $uuid = $this->input->query('filter');

        // 色相  300 表示保持色相保持不变
        // $h = 100;

        // 饱和度 有效范围为 0 ～ 200
        if (!isset($request['saturate']) || ((int)$request['saturate'] < 0) || ((int)$request['saturate'] > 200)) {
            throw new \Zeed_Exception('saturate not exist or format err');
        }

        // 明度 有效范围 0 ～ 200
        if (!isset($request['brigbtness']) || ((int)$request['brigbtness'] < 0) || ((int)$request['brigbtness'] > 200)) {
            throw new \Zeed_Exception('brigbtness not exist or format err');
        }

        // 对比度 有效范围 -100 ～ 100   // 
        if (!isset($request['contrast']) || ((int)$request['contrast'] < 0) || ((int)$request['contrast'] > 200)) {
            throw new \Zeed_Exception('contrast not exist or format err');
        }

        if ($request['saturate'] == 100 && $request['brigbtness'] == 100 && $request['contrast'] == 100) {
            return false;
        }

        $s = (int)$request['saturate'];
        $v = (int)$request['brigbtness'];
        $c = (int)$request['contrast'];

        // $c = $c - 100 > 100 ? 100 - $c : ((100 - $c ) > 100 ?  100 : 100 - $c );
        $c = $c < 100 ? $c - 100 : (int)(($c - 100) / 2);

        $exec_convert = " convert ";
        $exec_colorspace = " -set option:modulate:colorspace hsv -modulate ";
        $brigbtness = $v;
        $saturate = $s;
        $hue = $h;
        $outresult = " && echo success";
        $exec = $exec_convert . $this->sourcePath . $exec_colorspace . implode(",", [$brigbtness, $saturate]) . ' -brightness-contrast ' . implode(',', [0, $c]) . '  ' . $this->outPath . $outresult;
        $result = exec($exec);
        if (file_exists($this->outPath)) {
            $this->sourcePath = $this->outPath;
        } else {
            throw new Zeed_Exception($result, 203);
        }
    }

    // 旋转图片
    private function rotateImage()
    {
        $request = $uuid = $this->input->query('rotate');

        if ($request['angle'] == 0 || $request['angle'] == 360) {
            return false;   //无滤镜处理
        }

        //旋转角度 有效范围为 0 ～ 360 || ((int)$request->angle < 0) || ((int)$request->angle > 360)
        if (!isset($request['angle'])) {
            throw new \Zeed_Exception('angle not exist or format err', 302);
        }
        $angle = (int)$request['angle'];

        $imagick = new Imagick($this->sourcePath);
        $imagick->rotateImage(new ImagickPixel("rgba(255, 255, 255, 1)"), $angle);
        $imagick->writeImage($this->outPath);
        $this->sourcePath = $this->outPath;
    }

    // 同比例放大/缩小
    private function scaling()
    {
        $request = $uuid = $this->input->query('scaling');

        if (!$request['ratio'] == 1) {
            return false;   //无滤镜处理
        }
        //旋转角度 有效范围为 0 ～ 360
        if (!isset($request['ratio']) || ((int)$request['ratio'] < -10) || ((int)$request['ratio'] > 10)) {
            throw new \Zeed_Exception('ratio not exist or format err', 402);
        }
        $ratio = floatval($request['ratio']);
        $ratio = 1 + $ratio / 10;
        $imagick = new Imagick($this->sourcePath);
        $imageSize = $imagick->getImageGeometry();

        $width = $imageSize['width'] * $ratio;
        $height = $imageSize['height'] * $ratio;

        $imagick->thumbnailImage($width, $height);

        // 写图片内容
        $imagick->writeImage($this->outPath);
        $this->sourcePath = $this->outPath;
    }

    // 添加水印文字
    private function add_text(& $imagick, $text, $x = 0, $y = 0, $angle = 0, $style = array())
    {
        $draw = new ImagickDraw ();
        if (isset ($style ['font']))
            $draw->setFont($style ['font']);
        if (isset ($style ['font_size']))
            $draw->setFontSize($style ['font_size']);
        if (isset ($style ['fill_color']))
            $draw->setFillColor($style ['fill_color']);
        if (isset ($style ['under_color']))
            $draw->setTextUnderColor($style ['under_color']);
        if (isset ($style ['font_family']))
            $draw->setfontfamily($style ['font_family']);
        if (isset ($style ['font']))
            $draw->setfont($style ['font']);
        $draw->settextencoding('UTF-8');
        if (strtolower($imagick->getImageFormat()) == 'gif') {
            foreach ($imagick as $frame) {
                $frame->annotateImage($draw, $x, $y, $angle, $text);
            }
        } else {
            $imagick->annotateImage($draw, $x, $y, $angle, $text);
        }
    }

    /**
     * 添加水印
     */
    private function watermark()
    {
        $request = $uuid = $this->input->query('watermark');

        $zoom = $this->input->query('scaling');
        $ratio = floatval($zoom['ratio']);
        if (! $request['waterText']) {
            return false;
        }

	$imagick = new Imagick($this->sourcePath);
	$sourceImageInfo = $imagick->getImageGeometry();

        $watermark = $request['waterText'];
        $watermark_imagick = new Imagick();
        $watermarkW = $sourceImageInfo['width'];
        $watermarkH = $sourceImageInfo['height'];
        $color_transparent = new ImagickPixel('transparent'); //transparent 透明色
        $watermark_imagick->newImage($watermarkW, $watermarkH, $color_transparent, 'png');
        $style['font_size'] = $request['size'];
        $style['font'] = self::fontPath;
        $style['fill_color'] = $request['color'];
        $this->add_text($watermark_imagick, $watermark, 0, $request['height'] - 2, 0, $style);
        $watermark_imagick->setImageFormat('png');

        $ratio = 1 + $ratio / 10;
        $watermark_imagick->scaleImage($watermarkW * $ratio, $watermarkH * $ratio, true);

//        header ( "Content-Type: image/png" );
//        echo $watermark_imagick;
//        exit;

        $imagick->compositeImage($watermark_imagick, Imagick::COMPOSITE_OVER, $request['x'], $request['y']);
        // 写图片内容
        $imagick->writeImage($this->outPath);
        $this->sourcePath = $this->outPath;
    }

    // 添加水印
    private function watermark_bak()
    {

        $request = $uuid = $this->input->query('watermark');

        if (!$request['position']) {
            return false;
        }

        if (!$request['position'] || !in_array($request['position'], [1, 2, 3, 4])) {
            throw new Zeed_Exception(' position not exists', 503);
        }

        $water = new Imagick(self::water);
        $waterSize = $water->getImageGeometry();
        $waterwidth = $waterSize['width'];
        $waterheight = $waterSize['height'];

        $imagick = new Imagick($this->sourcePath);
        $imageSize = $imagick->getImageGeometry();
        $width = $imageSize['width'];
        $height = $imageSize['height'];

        switch ($request['position']) {
            case 1 :
                $x = $y = 0;
                break;

            case 2 :
                $x = $width - $waterwidth;
                $y = 0;
                break;

            case 3 :
                $x = $width - $waterwidth;

                $y = $height - $waterheight;
                break;

            case 4 :
                $x = 0;
                $y = $height - $waterheight;
                break;
        }

        $imagick->compositeImage($water, Imagick::COMPOSITE_OVER, $x, $y);

        // 写图片内容
        $imagick->writeImage($this->outPath);
        $this->sourcePath = $this->outPath;
    }

    // 裁剪
    private function tailoring()
    {
        $request = $uuid = $this->input->query('tailoring');

        if (!isset($request['x']) || !isset($request['y']) || !$request['width'] || !$request['height']) {
            throw new Zeed_Exception(' params err or not exists ', 602);
        }


        $imagick = new Imagick($this->sourcePath);
        $imageSize = $imagick->getImageGeometry();
        $width = $imageSize['width'];
        $height = $imageSize['height'];

        if ($request['x'] == 0 && $request['y'] == 0 && (($request['width'] == $width && $request['height'] == $height) || ($request['height'] == $width && $request['width'] == $height))) {
            return false;
        }

        if ($request['x'] < 0 || $request['y'] < 0 || ($request['x'] + $request['width']) > $width || ($request['y'] + $request['height']) > $height) {
            throw new Zeed_Exception(' request params over size ', 603);
        }

        $imagick->cropImage((int)$request['width'], (int)$request['height'], (int)$request['x'], (int)$request['y']);

        // 写图片内容
        $imagick->writeImage($this->outPath);
        $this->sourcePath = $this->outPath;
    }


    public static function fileextension($filepath)
    {

        $extension = substr($filepath, strrpos($filepath, "."));

        return $extension ? $extension : '';
    }

    public static function outFile($_id)
    {
        return md5($_id . time());
    }

    public static function initPath($path)
    {

        if (!file_exists($path)) {
            $mkdir = ' mkdir -m 777 -p ' . $path . ' && echo success ';

            $res = exec($mkdir);

            if ($res != "success") {
                throw new Zeed_Exception($path . " create failed ", -10);
            }
        }

    }

    private static function realSavePath($pathstr, $level = 5)
    {
        $split = str_split($pathstr, 2);

        $path = array_slice($split, 0, $level - 1);

        $filename = array_slice($split, $level - 1);

        return implode('/', $path) . '/' . implode('', $filename);
    }

    private static function realSavePathSameFolder($filepath)
    {

        $start = strrpos($filepath, '/') + 1;
        $length = strrpos($filepath, '.') - $start;
        $filename = substr($filepath, $start, $length);

        return str_replace($filename, $filename . '_' . Util_Timer::getMicrotime(), $filepath);
    }

    /**
     * 删除生产的图片
     */
    public function clipDelete()
    {
        $this->addResult(self::RS_SUCCESS, 'json');

        /* 接收参数 */
        $_id = trim($this->input->query('_id'));

        try {
            /* 检查请求方式 */
            if (!$this->input->isPOST()) {
                throw new Zeed_Exception('请求方式错误');
            }

            /* 检查请求参数 */
            if (!$_id) {
                throw new Zeed_Exception('缺少参数，或参数错误');
            }

            /* 检查文件是否存在 */
            $attachment_info = Attachment_Model_Content::instance()->fetchByPK($_id);
            if (empty($attachment_info)) {
                throw new Zeed_Exception('查无此文件');
            }
            $attachment_info = $attachment_info[0];

            /* 执行删除 */
            $set = array(
                'status' => -1,
                'mtime' => Util_Timer::getMicrotime()
            );
            Attachment_Model_Content::instance()->updateForEntity($set, $_id);

            /* @todo 新增一条日志记录 */

        } catch (Zeed_Exception $e) {
            $this->setStatus($e->getCode() ? $e->getCode() : 1);
            $this->setError('删除失败 : ' . $e->getMessage());
        }

        return self::RS_SUCCESS;
    }
}

// End ^ LF ^ encoding
